﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace CreateJM
{
    class Program
    {
        enum WuBi { WuBi86 = 1, WuBi98, WuBi06,WuBiAll};
        enum WordType { cy3500 = 1, ty7000, gf8105, GB18030_2000, unicode_trokesRadicals, unicodeCJK };

        static void Main(string[] args)
        {
            //Console.ForegroundColor = ConsoleColor.Yellow;
            //Console.WriteLine("\r\n                    欢迎使有【极光五笔】单字编码生成工具\r\n");
            //Console.ForegroundColor = ConsoleColor.Green;
            //Console.WriteLine("                本词库的特点：自动为单字生成简码，最多3重\r\n");
            //Console.ForegroundColor = ConsoleColor.Red;
            //Console.WriteLine("                  1=WuBi86, 2=WuBi98, 3=WuBi06,4=WuBiAll\r\n");
            //Console.WriteLine("1=cy3500, 2=ty700, 3=gf8105, 4=GB18030_2000, 5=unicode_trokesRadicals, 6=unicodeCJK\r\n");
            //Console.ForegroundColor = ConsoleColor.White;
            //Console.WriteLine("                            按任意键继续！");
            //Console.ReadLine();
            Console.WriteLine(string.Format("五笔：{0}-WuBi86,{1}-WuBi98,{2}-WuBi06", (int)WuBi.WuBi86, (int)WuBi.WuBi98, (int)WuBi.WuBi06));
            Console.WriteLine(string.Format("字集：{0}- cy3500,{1}-ty7000,{2}-gf8105,{3}-GB18030_2000,{4}-unicode_trokesRadicals,{5}-unicodeCJK", (int)WordType.cy3500, (int)WordType.ty7000, (int)WordType.gf8105, (int)WordType.GB18030_2000, (int)WordType.unicode_trokesRadicals, (int)WordType.unicodeCJK));
            Console.WriteLine(string.Format("本次生成单字：{0},{1}", (WuBi)int.Parse((args[0])), (WordType)int.Parse((args[1]))));

            //  CreateWuBiDZ(WuBi.WuBi06, WordType.GB18030_2000);

            CreateWuBiDZ((WuBi)int.Parse((args[0])), (WordType)int.Parse((args[1])));
        }

        /// <summary>
        /// 从源源UnicodeCJK，生成rime,极点、sougou格式的CKJ
        /// </summary>
        static void CreateWuBiDZ(WuBi wuBi, WordType wordType = WordType.GB18030_2000 )
        {
            string filesDirectoryUnicode = "源UnicodeCJK";
            string filesJM1 = @"源数据/一级简码.txt";
            string filesJMZ = @"源数据/键面字.txt";
            string filesJM2 = @"源数据/wubi06二级简码.txt";

            switch(wuBi)
            {
                case WuBi.WuBi86:
                    filesJM2 = @"源数据/wubi86二级简码.txt";
                    break;
                case WuBi.WuBi98:
                    filesJM2 = @"源数据/wubi98二级简码.txt";
                    break;
                default:
                    break;

            }

            string filesCH3500 = @"源数据/常用字3500.txt";


            string filesTY7000 = @"源数据/通用汉字7000.txt";
            string filesGF8105 = @"源数据/规范汉字8105.txt";
            string filesGB18030_2000 = @"源数据/GB18030_2000.txt";
            string filesZipin = @"源数据/字频合集.txt";
            string filesCJKStrokes = @"源UnicodeCJK/CJKStrokes.txt";//笔画
            string filesCJKRadicalsSupplement = @"源UnicodeCJK/CJKRadicalsSupplement.txt";//CJK部首补充


            Dictionary<string, UnicodeWordInfo> dictUnicodeWordsInfo = new Dictionary<string, UnicodeWordInfo>();
            Dictionary<string, WordCodeInfo> dictWordCodeInfo86 = new Dictionary<string, WordCodeInfo>();
            Dictionary<string, WordCodeInfo> dictWordCodeInfo98 = new Dictionary<string, WordCodeInfo>();
            Dictionary<string, WordCodeInfo> dictWordCodeInfo06 = new Dictionary<string, WordCodeInfo>();

            Dictionary<string, WordType> dicWordType = new Dictionary<string, WordType>();
           

            String[] files = Directory.GetFiles(filesDirectoryUnicode, "*.*", SearchOption.AllDirectories);
            foreach (string file in files)
            {
                Console.WriteLine("\r\n开始读取["+ filesDirectoryUnicode+"]:" + file);

                using (StreamReader sr = new StreamReader(file, Encoding.UTF8))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (line.Length > 0)
                        {
                            try
                            {
                                string[] info = line.Split(new string[] { "," }, StringSplitOptions.None);
                                if (info[1].Length == 0)
                                    continue;
     

                                UnicodeWordInfo word = new UnicodeWordInfo(info[0], info[1], info[2], info[3], info[4], info[5], info[6]);
                                dictUnicodeWordsInfo.Add(info[1], word);

                                if(info[2].Length>0)
                                {
                                    WordCodeInfo wordCodeInfo86 = new WordCodeInfo(info[1], info[2]);
                                    dictWordCodeInfo86.Add(info[1], wordCodeInfo86);
                                }

                                if (info[3].Length > 0)
                                {
                                    WordCodeInfo wordCodeInfo98 = new WordCodeInfo(info[1], info[3]);
                                    dictWordCodeInfo98.Add(info[1], wordCodeInfo98);
                                }

                                if(info[4].Length>0)
                                {
                                    WordCodeInfo wordCodeInfo06 = new WordCodeInfo(info[1], info[4]);
                                    dictWordCodeInfo06.Add(info[1], wordCodeInfo06);
                                }
                                
                            }
                            catch
                            {
                                Console.WriteLine("\r\n解析源UnicodeCJK遇到错误：" + line);
                            }
                        }
                    }
                }
                ClearConsoleLine(2);
                Console.WriteLine("\r\n读取源UnicodeCJK成功：" + file);
            }

            //25个固定一级简码
            Dictionary<string, string> wordToCodeJMs25 = new Dictionary<string, string>();
            //一个码有哪些字
            Dictionary<string, List<string>> codeToWord86 = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> codeToWord98 = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> codeToWord06 = new Dictionary<string, List<string>>();
            List<string> JM1 = new List<string>();
            List<string> JM2 = new List<string>();
            List<string> JM3 = new List<string>();
            Dictionary<string, List<string>> newcodetoword86 = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> newcodetoword98 = new Dictionary<string, List<string>>();
            Dictionary<string, List<string>> newcodetoword06 = new Dictionary<string, List<string>>();

            //计算出所有字符的级别wordlevel
            Dictionary<string, int> wordlevel = new Dictionary<string, int>();

            //读取一级简码
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesJM1);
            using (StreamReader sr = new StreamReader(filesJM1, Encoding.UTF8))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] ArrWordCode = line.Split(new string[] { "\t" }, StringSplitOptions.None);
                    string keyWord = ArrWordCode[0].ToString();
                    string codeWord = ArrWordCode[1].ToString();

                    wordToCodeJMs25.Add(keyWord, codeWord);

                    codeToWord86.Add(codeWord, new List<string>() { keyWord });
                    codeToWord98.Add(codeWord, new List<string>() { keyWord });
                    codeToWord06.Add(codeWord, new List<string>() { keyWord });

                    JM1.Add(keyWord);
                    JM2.Add(keyWord);
                    JM3.Add(keyWord);
                    newcodetoword86.Add(codeWord, new List<string>() { keyWord });
                    newcodetoword98.Add(codeWord, new List<string>() { keyWord });
                    newcodetoword06.Add(codeWord, new List<string>() { keyWord });

                    wordlevel.Add(keyWord, 1);
                }
            }

           
            #region 计算出所有字符的级别wordlevel：原一级简码1级，原键面字2级，原二级简码3级， 一级常用2000字4级， 二级常用1500字5级；7000+8105+GB18030_2000+笔画、部首jvm第6级为6级，其他CJK为7级
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesJMZ);
            using (StreamReader srJMZ = new StreamReader(filesJMZ, Encoding.UTF8))
            {
                string line;
                while ((line = srJMZ.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] ArrWordCode = line.Split(new string[] { "\t" }, StringSplitOptions.None);
                        string keyWord = ArrWordCode[0].ToString();
                        if (!wordlevel.ContainsKey(keyWord))
                            wordlevel.Add(keyWord, 2);
                    }
                }
            }
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesJM2);
            using (StreamReader srJM2 = new StreamReader(filesJM2, Encoding.UTF8))
            {
                string line;
                while ((line = srJM2.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        if (!wordlevel.ContainsKey(line))
                            wordlevel.Add(line, 3);
                    }
                }
            }

            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesCH3500);
            using (StreamReader sr3500 = new StreamReader(filesCH3500, Encoding.UTF8))
            {
                string line;
                while ((line = sr3500.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] ArrWordCode = line.Split(new string[] { "\t" }, StringSplitOptions.None);
                        string keyWord = ArrWordCode[0].ToString();
                        int levl = int.Parse(ArrWordCode[1].ToString());

                        if (!wordlevel.ContainsKey(keyWord))
                            wordlevel.Add(keyWord, levl+3);

                        if(!dicWordType.ContainsKey(keyWord))
                             dicWordType.Add(keyWord, WordType.cy3500);
                    }
                }
            }
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesTY7000);
            using (StreamReader sr7000 = new StreamReader(filesTY7000, Encoding.UTF8))
            {
                string line;
                while ((line = sr7000.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        if (!wordlevel.ContainsKey(line))
                            wordlevel.Add(line, 6);

                        if (!dicWordType.ContainsKey(line))
                            dicWordType.Add(line, WordType.ty7000);
                    }
                }
            }
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesGF8105);
            using (StreamReader sr8105 = new StreamReader(filesGF8105, Encoding.UTF8))
            {
                string line;
                while ((line = sr8105.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        if (!wordlevel.ContainsKey(line))
                            wordlevel.Add(line, 6);

                        if (!dicWordType.ContainsKey(line))
                            dicWordType.Add(line, WordType.gf8105);
                    }
                }
            }
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesGB18030_2000);
           // List<string> word18030_2000 = new List<string>();
            using (StreamReader sr18030 = new StreamReader(filesGB18030_2000, Encoding.UTF8))
            {
                string line;
                while ((line = sr18030.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                       // word18030_2000.Add(line);

                        if (!wordlevel.ContainsKey(line))
                            wordlevel.Add(line, 6);

                        if (!dicWordType.ContainsKey(line))
                            dicWordType.Add(line, WordType.GB18030_2000);
                    }
                }
            }

            //笔画、部首归第5个级别
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesCJKStrokes);
            //List<string> wordCJKStrokes = new List<string>();
            using (StreamReader srCJKStrokes = new StreamReader(filesCJKStrokes, Encoding.UTF8))
            {
                string line;
                while ((line = srCJKStrokes.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] info = line.Split(new string[] { "," }, StringSplitOptions.None);
                        if (info[1].Trim().Length == 0)
                            continue;

                       // wordCJKStrokes.Add(line);

                        if (!wordlevel.ContainsKey(info[1].Trim()))
                            wordlevel.Add(info[1].Trim(), 6);

                        if (!dicWordType.ContainsKey(info[1].Trim()))
                            dicWordType.Add(info[1].Trim(), WordType.unicode_trokesRadicals);
                    }
                }
            }
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesCJKRadicalsSupplement);
           // List<string> wordCJKRadicalsSupplement = new List<string>();
            using (StreamReader srCJKRadicalsSupplement = new StreamReader(filesCJKRadicalsSupplement, Encoding.UTF8))
            {
                string line;
                while ((line = srCJKRadicalsSupplement.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] info = line.Split(new string[] { "," }, StringSplitOptions.None);
                        if (info[1].Trim().Length == 0)
                            continue;

                        // wordCJKRadicalsSupplement.Add(line);

                        if (!wordlevel.ContainsKey(info[1].Trim()))
                            wordlevel.Add(info[1].Trim(), 6);

                        if (!dicWordType.ContainsKey(info[1].Trim()))
                            dicWordType.Add(info[1].Trim(), WordType.unicode_trokesRadicals);
                    }
                }
            }

            //StringBuilder stringBuilder = new StringBuilder();
            //foreach(KeyValuePair<string,int> kvp in wordlevel)
            //{
            //    stringBuilder.Append(kvp.Key +"\t"+ kvp.Value + "\r\n");
            //}
            //StreamWriter wubi3 = new StreamWriter("生成/" + "字级别合集.txt", false, Encoding.Unicode);

            //wubi3.Write(stringBuilder.ToString());

            //wubi3.Flush();
            //wubi3.Close();


            //剩余的字归第7个级别
            foreach (KeyValuePair<string, UnicodeWordInfo> kvp in dictUnicodeWordsInfo)
            {
                if (!wordlevel.ContainsKey(kvp.Key))
                    wordlevel.Add(kvp.Key, 6);

                if (!dicWordType.ContainsKey(kvp.Key))
                    dicWordType.Add(kvp.Key, WordType.unicodeCJK);
            }
            #endregion


            Dictionary<string, int> ZPkeys = new Dictionary<string, int>();
            ClearConsoleLine(2);
            Console.WriteLine("\r\n开始读取：" + filesZipin);
            using (StreamReader sr = new StreamReader(filesZipin, Encoding.UTF8))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] ArrWordCode = line.Split(new string[] { "\t" }, StringSplitOptions.None);
                        string keyWord = ArrWordCode[0].ToString();
                        int codeWord = int.Parse(ArrWordCode[1].ToString());

                        ZPkeys.Add(keyWord, codeWord);
                    }
                }
            }

            //一个码有哪些字
            switch (wuBi)
            {
                case WuBi.WuBi86:
                    Console.WriteLine("\r\n准备生成单字：" + wuBi.ToString()+"；"+ wordType.ToString());
                    codeToWord86 = CodeToWord(codeToWord86, dictWordCodeInfo86);
                    newcodetoword86 = Newcodetoword(codeToWord86, ZPkeys,dicWordType, wordlevel, wordType, newcodetoword86, JM1, JM2, JM3, dictWordCodeInfo86);
                    WriterWuBi(wuBi, newcodetoword86, wordType, dictWordCodeInfo86);
                    break;
                case WuBi.WuBi98:
                    Console.WriteLine("\r\n准备生成单字：" + wuBi.ToString() + "；" + wordType.ToString());
                    codeToWord98 = CodeToWord(codeToWord98, dictWordCodeInfo98);
                    newcodetoword98 = Newcodetoword(codeToWord98, ZPkeys, dicWordType, wordlevel, wordType, newcodetoword98, JM1, JM2, JM3, dictWordCodeInfo98);
                    WriterWuBi(wuBi, newcodetoword98, wordType, dictWordCodeInfo98);
                    break;
                case WuBi.WuBi06:
                    Console.WriteLine("\r\n准备生成单字：" + wuBi.ToString() + "；" + wordType.ToString());
                    codeToWord06 = CodeToWord(codeToWord06, dictWordCodeInfo06);
                    newcodetoword06 = Newcodetoword(codeToWord06, ZPkeys, dicWordType, wordlevel, wordType, newcodetoword06, JM1, JM2, JM3, dictWordCodeInfo06);
                    WriterWuBi(wuBi, newcodetoword06, wordType, dictWordCodeInfo06);
                    break;
                default:
                    Console.WriteLine("\r\n准备生成单字：" + WuBi.WuBi86.ToString() + "；" + wordType.ToString());
                    codeToWord86 = CodeToWord(codeToWord86, dictWordCodeInfo86);
                    newcodetoword86 = Newcodetoword(codeToWord86, ZPkeys, dicWordType, wordlevel, wordType, newcodetoword86, JM1, JM2, JM3, dictWordCodeInfo86);
                    WriterWuBi(WuBi.WuBi86, newcodetoword86, wordType, dictWordCodeInfo86);

                    Console.WriteLine("\r\n准备生成单字：" + WuBi.WuBi98.ToString() + "；" + wordType.ToString());
                    codeToWord98 = CodeToWord(codeToWord98, dictWordCodeInfo98);
                    newcodetoword98 = Newcodetoword(codeToWord98, ZPkeys, dicWordType, wordlevel, wordType, newcodetoword98, JM1, JM2, JM3, dictWordCodeInfo98);
                    WriterWuBi(WuBi.WuBi98, newcodetoword98, wordType, dictWordCodeInfo98);

                    Console.WriteLine("\r\n准备生成单字：" + WuBi.WuBi06.ToString() + "；" + wordType.ToString());
                    codeToWord06 = CodeToWord(codeToWord06, dictWordCodeInfo06);
                    newcodetoword06 = Newcodetoword(codeToWord06, ZPkeys, dicWordType, wordlevel, wordType, newcodetoword06, JM1, JM2, JM3, dictWordCodeInfo06);
                    WriterWuBi(WuBi.WuBi06, newcodetoword06, wordType, dictWordCodeInfo06);


                    break;
            }

           // Console.ReadLine();
        }
    

    static Dictionary<string, List<string>> CodeToWord(Dictionary<string, List<string>> codeToWord, Dictionary<string, WordCodeInfo> dictWordCodeInfo)
        {
            
            Console.WriteLine("\r\n计算编码所对应的全部字");
            foreach (KeyValuePair<string, WordCodeInfo> kvp in dictWordCodeInfo)
            {

                if (!codeToWord[kvp.Value.Code1].Contains(kvp.Key))
                    codeToWord[kvp.Value.Code1].Add(kvp.Key);

                if (!codeToWord.ContainsKey(kvp.Value.Code2))
                {
                    codeToWord.Add(kvp.Value.Code2, new List<string>() { kvp.Key });
                }
                else
                {
                    codeToWord[kvp.Value.Code2].Add(kvp.Key);
                }

                if (!string.IsNullOrEmpty(kvp.Value.Code3))
                {
                    if (!codeToWord.ContainsKey(kvp.Value.Code3))
                    {
                        codeToWord.Add(kvp.Value.Code3, new List<string>() { kvp.Key });
                    }
                    else
                    {
                        codeToWord[kvp.Value.Code3].Add(kvp.Key);
                    }
                }

                if (!string.IsNullOrEmpty(kvp.Value.Code4))
                {
                    if (!codeToWord.ContainsKey(kvp.Value.Code4))
                    {
                        codeToWord.Add(kvp.Value.Code4, new List<string>() { kvp.Key });
                    }
                    else
                    {
                        codeToWord[kvp.Value.Code4].Add(kvp.Key);
                    }
                }
            }
            return codeToWord;
        }
        /// <summary>
        /// 生成新的一码多字X重
        /// </summary>
        /// <param name="multipleCoding">重码数，默认3重</param>
        /// <param name="ZPkeys">字频</param>
        /// /// <param name="dicWordType">汉字分类</param>
        /// <param name="wordlevel">汉字级别</param>
        /// <param name="wordType">汉字级别类型</param>
        /// <param name="newcodetoword">新的一码多字，最多X重</param>
        /// <param name="JM1">是否为一级简码</param>
        /// <param name="JM2">是否为一级简码或二级简码</param>
        /// <param name="JM3">是否为一级简码或二级简码或三级简码</param>
        /// <param name="dictWordCodeInfo">一个汉字的所有编码信息</param>
        /// <param name="codeToWord">原一码多字所有值</param>
        static Dictionary<string, List<string>> Newcodetoword( Dictionary<string, List<string>> codeToWord, Dictionary<string, int> ZPkeys, Dictionary<string, WordType> dicWordType, Dictionary<string, int> wordlevel, WordType wordType, Dictionary<string, List<string>> newcodetoword, List<string> JM1, List<string> JM2, List<string> JM3, Dictionary<string, WordCodeInfo> dictWordCodeInfo, int multipleCoding=3)
        {
           // Regex regex = new Regex("[a-y]*h$|[a-y]*j$|[a-y]*k$|[a-y]*l$|[a-y]*m$|[a-y]*n$|[a-y]*y$|[a-y]*u$|[a-y]*i$|[a-y]*o$|[a-y]*p$");
            //1码
            Console.WriteLine("开始处理1码");
            for (char i = 'a'; i <= 'y'; i++)
            {
                ClearConsoleLine(1);
                Console.WriteLine("开始处理1码:" + i.ToString());

                //if (regex.IsMatch(i.ToString()))
                //{
                //    multipleCoding--;
                //}
                List<WordFrequencyInfo> myWordSort = new List<WordFrequencyInfo>();
                foreach (string s in codeToWord[i.ToString()])
                {
                    int f2 = 1;
                    if (ZPkeys.ContainsKey(s))
                        f2 = ZPkeys[s];

                    myWordSort.Add(new WordFrequencyInfo(s, wordlevel[s], f2));
                }
                myWordSort.Sort(WordFrequencySort.SortByFrequency);

                int j = 2;
                foreach (WordFrequencyInfo w in myWordSort)
                {
                    if ((int)dicWordType[w.Word] > ((int)wordType))
                        continue;

                    if (!JM1.Contains(w.Word))
                    {
                        if(j<= 2)
                        {
                            newcodetoword[i.ToString()].Add(w.Word);
                            JM1.Add(w.Word);
                            JM2.Add(w.Word);
                            JM3.Add(w.Word);
                            j++;
                        }
                        else
                        {
                            break;
                        }
 
                    }
                }
            }
            #region 2码
            Console.WriteLine("开始处理2码");
            for (char i = 'a'; i <= 'y'; i++)
            {
                ClearConsoleLine(1);
                Console.WriteLine("开始处理2码:" + i.ToString() + "*组");
                for (char i2 = 'a'; i2 <= 'y'; i2++)
                {
                    string zm = i.ToString() + i2.ToString();
                    List<WordFrequencyInfo> myWordSort = new List<WordFrequencyInfo>();
                    foreach (string s in codeToWord[zm])
                    {
                        int f2 = 1;
                        if (ZPkeys.ContainsKey(s))
                            f2 = ZPkeys[s];

                        myWordSort.Add(new WordFrequencyInfo(s, wordlevel[s], f2));
                    }
                    myWordSort.Sort(WordFrequencySort.SortByFrequency);

                    int j = 1;
                    List<string> st = new List<string>();
                    foreach (WordFrequencyInfo w in myWordSort)
                    {
                        if ((int)dicWordType[w.Word] > ((int)wordType))
                            continue;
                        

                        if (!JM2.Contains(w.Word))
                        {
                            if (j <= 2)
                            {
                                if (newcodetoword.ContainsKey(zm))
                                    newcodetoword[zm].Add(w.Word);
                                else
                                    newcodetoword.Add(zm, new List<string>() { w.Word });

                                JM2.Add(w.Word);
                                JM3.Add(w.Word);
                                j++;
                            }
                            else//超过3重，判断该码是否为全码，是全码也显示
                            {
                                if (dictWordCodeInfo[w.Word].Code.Length == 2)
                                    st.Add(w.Word);
                            }
                        }
                        else//如果已有简码，判断该码是否为全码，是全码也显示
                        {
                            if (dictWordCodeInfo[w.Word].Code.Length == 2)
                                st.Add(w.Word);
                        }
                    }
                    if (st.Count > 0)
                    {
                        foreach (string s1 in st)
                        {
                            if (newcodetoword.ContainsKey(zm))
                                newcodetoword[zm].Add(s1);
                            else
                                newcodetoword.Add(zm, new List<string>() { s1 });
                        }
                    }
                }

            }
            #endregion
            #region 3码
            Console.WriteLine("开始处理3码");
            for (char i = 'a'; i <= 'y'; i++)
            {
                ClearConsoleLine(1);
                Console.WriteLine("开始处理3码:" + i.ToString()  + "**组");
                for (char i2 = 'a'; i2 <= 'y'; i2++)
                {
                    for (char i3 = 'a'; i3 <= 'y'; i3++)
                    {
                        string zm = i.ToString() + i2.ToString() + i3.ToString();

                        if (!codeToWord.ContainsKey(zm))
                            continue;
                        List<WordFrequencyInfo> myWordSort = new List<WordFrequencyInfo>();
                        foreach (string s in codeToWord[zm])
                        {
                            int f2 = 1;
                            if (ZPkeys.ContainsKey(s))
                                f2 = ZPkeys[s];

                            myWordSort.Add(new WordFrequencyInfo(s, wordlevel[s], f2));
                        }
                        myWordSort.Sort(WordFrequencySort.SortByFrequency);

                        int j = 1;
                        List<string> st = new List<string>();
                        foreach (WordFrequencyInfo w in myWordSort)
                        {
                            if ((int)dicWordType[w.Word] > ((int)wordType))
                                continue;

                            if (!JM3.Contains(w.Word))
                            {
                                if(j<= 2)
                                {
                                    if (newcodetoword.ContainsKey(zm))
                                        newcodetoword[zm].Add(w.Word);
                                    else
                                        newcodetoword.Add(zm, new List<string>() { w.Word });

                                    JM3.Add(w.Word);
                                    j++;
                                }
                                else//超过3重，判断该码是否为全码，是全码也显示
                                {
                                    if (dictWordCodeInfo[w.Word].Code.Length == 3)
                                        st.Add(w.Word);
                                }
                            }
                            else//如果已有简码，判断该码是否为全码，是全码也显示
                            {
                                if (dictWordCodeInfo[w.Word].Code.Length == 3)
                                    st.Add(w.Word);
                            }
                        }
                        if (st.Count > 0)
                        {
                            foreach (string s1 in st)
                            {
                                if (newcodetoword.ContainsKey(zm))
                                    newcodetoword[zm].Add(s1);
                                else
                                    newcodetoword.Add(zm, new List<string>() { s1 });
                            }
                        }
                    }

                }
            }
            #endregion

            #region 4码
            for (char i = 'a'; i <= 'y'; i++)
            {
                for (char i2 = 'a'; i2 <= 'y'; i2++)
                {
                    ClearConsoleLine(1);
                    Console.WriteLine("开始处理4码:" + i.ToString() + i2.ToString()  + "**组");
                    for (char i3 = 'a'; i3 <= 'y'; i3++)
                    {
                        for (char i4 = 'a'; i4 <= 'y'; i4++)
                        {
                            string zm = i.ToString() + i2.ToString() + i3.ToString() + i4.ToString();
                            if (!codeToWord.ContainsKey(zm))
                                continue;

                            List<WordFrequencyInfo> myWordSort = new List<WordFrequencyInfo>();
                            foreach (string s in codeToWord[zm])
                            {
                                int f2 = 1;
                                if (ZPkeys.ContainsKey(s))
                                    f2 = ZPkeys[s];

                                myWordSort.Add(new WordFrequencyInfo(s, wordlevel[s], f2));
                            }
                            myWordSort.Sort(WordFrequencySort.SortByFrequency);

                            List<string> st = new List<string>();
                            foreach (WordFrequencyInfo w in myWordSort)
                            {
                                if ((int)dicWordType[w.Word] > ((int)wordType))
                                    continue;

                                if (!JM3.Contains(w.Word))
                                {
                                    if (newcodetoword.ContainsKey(zm))
                                        newcodetoword[zm].Add(w.Word);
                                    else
                                        newcodetoword.Add(zm, new List<string>() { w.Word });
                                }
                                else//有简码则加到后面
                                {
                                    st.Add(w.Word);
                                }

                            }

                            if (st.Count > 0)
                            {
                                foreach (string s1 in st)
                                {
                                    if (newcodetoword.ContainsKey(zm))
                                        newcodetoword[zm].Add(s1);
                                    else
                                        newcodetoword.Add(zm, new List<string>() { s1 });
                                }
                            }
                        }

                    }

                }
            }
            #endregion
            return newcodetoword;
        }
    
        /// <summary>
        /// 生成wubui文件
        /// </summary>
        /// <param name="wuBi">五笔类型</param>
        /// <param name="newcodetoword">一码多字字典</param>
        /// <param name="wordType">字符类型</param>
        static void WriterWuBi(WuBi wuBi,Dictionary<string, List<string>> newcodetoword, WordType wordType, Dictionary<string, WordCodeInfo> dictWordCodeInfo)
        {
            List<string> allCode = newcodetoword.Keys.ToList();
            allCode.Sort();

            if (false == System.IO.Directory.Exists("生成"))
            {
                System.IO.Directory.CreateDirectory("生成");
            }

            StringBuilder sbRime3 = new StringBuilder();
            StringBuilder sbSoGou3 = new StringBuilder();
            StringBuilder sbJiDian3 = new StringBuilder();

            Console.WriteLine("准备生成文件");
            List<string> allWord = new List<string>();
            foreach (string code in allCode)
            {
                //ClearConsoleLine();
                //Console.WriteLine("准备生成文件，当前编码："+ code);

                StringBuilder stringBuilder = new StringBuilder();
                foreach (string word in newcodetoword[code])
                {
                    sbRime3.Append(word + "\t" + code + "\t" + "1" + "\t" + dictWordCodeInfo[word].Code.Substring(0,2) + "\r\n");
                    sbSoGou3.Append(code + "\t" + word + "\r\n");

                    stringBuilder.Append(word).Append(" ");

                    if (!allWord.Contains(word))
                        allWord.Add(word);
                }

                if (stringBuilder.Length > 1)
                    stringBuilder.Remove(stringBuilder.Length - 1, 1);

                sbJiDian3.Append(code + " " + stringBuilder.ToString() + "\r\n");
            }


            Console.WriteLine("开始写入文件");
            StreamWriter rimewubi3 = new StreamWriter("生成/" + wuBi.ToString() + "_" + wordType.ToString() + "_dz_rime.txt", false, new UTF8Encoding(false));
            StreamWriter sogouwubi3 = new StreamWriter("生成/" + wuBi.ToString() + "_" + wordType.ToString() + "_dz_sogou.txt", false, new UTF8Encoding(false));
            StreamWriter jidianwubi3 = new StreamWriter("生成/" + wuBi.ToString() + "_" + wordType.ToString() + "_dz_jidian.txt", false, Encoding.Unicode);

            rimewubi3.Write(sbRime3.ToString());
            sogouwubi3.Write(sbSoGou3.ToString());
            jidianwubi3.Write(sbJiDian3.ToString());


            rimewubi3.Flush();
            rimewubi3.Close();

            sogouwubi3.Flush();
            sogouwubi3.Close();

            jidianwubi3.Flush();
            jidianwubi3.Close();


            StreamWriter txtwubi3 = new StreamWriter("生成/" + wuBi.ToString() + "_" + wordType.ToString() + "_txt.txt", false, new UTF8Encoding(false));

            txtwubi3.Write("生成【{0}】类型【{1}】汉字数量：{2}；编码数量：{3}\r\n", wuBi.ToString(), wordType.ToString(), allWord.Count, allCode.Count);
            foreach (string sz in allWord)
            {
                txtwubi3.Write(sz+"\r\n");
            }
           
            txtwubi3.Flush();
            txtwubi3.Close();

            Console.WriteLine("生成【{0}】类型【{1}】汉字数量：{2}；编码数量：{3}", wuBi.ToString(), wordType.ToString(),allWord.Count,allCode.Count);
        }
        /// <summary>
        /// 清除控制台指定第几行数的内容
        /// </summary>
        /// <param name="invertedIndex">1为最后一行</param>
        public static void ClearConsoleLine(int invertedIndex = 1)
        {
            int currentLineCursor = Console.CursorTop;
            int top = Console.CursorTop - invertedIndex;
            top = top < 0 ? 0 : top;
            Console.SetCursorPosition(0, top);
            Console.Write(new string(' ', Console.WindowWidth - 1));
            Console.SetCursorPosition(0, currentLineCursor-1);
        }
    }
}
